home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / unitxrf.com / UNITXREF.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1991-05-20  |  7.9 KB  |  294 lines

  1. Unit UnitXref;
  2. {**************************************************************************}
  3. {*  UnitXref                                                              *}
  4. {*                                                                        *}
  5. {*    Donated to the Public Domain 5/20/91 by Dan Thomas CIS: 72301,2164  *}
  6. {*                                                                        *}
  7. {*  NOTE: YOU MUST SET YOUR STACK SIZE HIGHER TO USE THIS UNIT, AS IN:    *}
  8. {*                                                                        *}
  9. {*              {$M 32768,0,655360}                                      {*}
  10. {*                                                                        *}
  11. {*  The UnitCrossReference function will return a pStringCollection       *}
  12. {*  containing file names for all units referenced by the specified       *}
  13. {*  program source file.                                                  *}
  14. {*                                                                        *}
  15. {*  This routine scans all "Used" units, also.                            *}
  16. {*                                                                        *}
  17. {*  The function GetThePath(FileID) returns the path that the file ID     *}
  18. {*  is in.                                                                *}
  19. {*                                                                        *}
  20. {*  NOTE: The typed constant "UnitSearchPath" is a string that contains   *}
  21. {*        a search path for units.  You may change it if needed.          *}
  22. {*        This unit always checks the path of the source file first,      *}
  23. {*        then it uses the path (when looking for units).                 *}
  24. {**************************************************************************}
  25.  
  26. INTERFACE
  27.  
  28. Uses DOS,Objects,PathID,FilExist,ProgErr;
  29.  
  30. CONST
  31.   UnitSearchPath : string =
  32.       'C:\TP\TVISION;C:\TP\TPU;C:\TP\UNIT;';
  33.  
  34. TYPE
  35.   pFileBuff=^tFileBuff;
  36.   tFileBuff=array[1..10240] of byte;
  37.  
  38. VAR
  39.   CurrStartCommentDelim,
  40.   FirstFileID,
  41.   RootDir      : string;
  42.  
  43.  
  44. FUNCTION UnitCrossReference(SourceFileID: string): pStringCollection;
  45. FUNCTION GetThePath(FileID: string): string;
  46.  
  47. IMPLEMENTATION
  48.  
  49. FUNCTION StripRec(s : string) : string;
  50.  
  51. var
  52.   x,last_non_space  : byte;
  53.   s1 : string;
  54.  
  55. begin
  56.   s1 := '';
  57.   last_non_space := 0;
  58.   for x := 1 to length(s) do s[x] := Upcase(s[x]);
  59.   for x := 1 to length(s) do begin
  60.     if CurrStartCommentDelim = '' then
  61.       if (s[x] = '{') and (copy(s,x,4) <> '{$I ') then
  62.         CurrStartCommentDelim := '{'
  63.       else
  64.       if (x < length(s)) and (s[x] = '(') and (s[x+1] = '*') then
  65.         CurrStartCommentDelim := '(*'
  66.       else
  67.       if (s[x] <> ' ') or (s1 <> '') then
  68.         begin
  69.           s1[length(s1)+1] := s[x];
  70.           s1[0] := char(length(s1)+1);
  71.           if s[x] <> ' ' then
  72.             last_non_space := length(s1);
  73.         end
  74.       else
  75.         begin end
  76.     else
  77.     if (s[x] = '}') and (CurrStartCommentDelim = '{') then
  78.       CurrStartCommentDelim := ''
  79.     else
  80.     if (x < length(s)) and (s[x] = '*') and (s[x+1] = ')')
  81.         and (CurrStartCommentDelim = '(*') then
  82.       CurrStartCommentDelim := '';
  83.   end; {of for}
  84.   s1[0] := char(last_non_space);
  85.   StripRec := s1;
  86. end; {StripRec}
  87.  
  88. FUNCTION GetThePath(FileID: string): string;
  89.  
  90. var
  91.   p,s,s1 : string;
  92.   x : byte;
  93.  
  94. begin
  95.   GetThePath := '';
  96.   if file_exists(RootDir+FileID) then
  97.     begin
  98.       GetThePath := RootDir;
  99.       exit;
  100.     end;
  101.  
  102.   s := StripRec(UnitSearchPath);
  103.   While (s <> '') do begin
  104.     x := pos(',',s);
  105.     if x = 0 then
  106.       x := pos(';',s);
  107.     if x = 0 then
  108.       x := length(s) + 1;
  109.     p := StripRec(copy(s,1,x-1));
  110.     s1 := path_plus_file_id(p,FileID);
  111.     if file_exists(s1) then
  112.       begin
  113.         GetThePath := p;
  114.         exit;
  115.       end;
  116.     if x > length(s) then
  117.       s := ''
  118.     else
  119.       delete(s,1,x);
  120.   end; {of While}
  121. end; {GetThePath}
  122.  
  123. FUNCTION UnitCrossReference(SourceFileID: string): pStringCollection;
  124.  
  125. VAR
  126.   UnitColl     : pStringCollection;
  127.  
  128. PROCEDURE Initialize;
  129.  
  130. var
  131.   n,e : string;
  132.  
  133. begin
  134.   FSplit(FExpand(SourceFileID),RootDir,n,e);
  135.   UnitColl := New(pStringCollection,init(500,100));
  136.   CurrStartCommentDelim := '';
  137.   FirstFileID := '';
  138. end; {Initialize}
  139.  
  140. PROCEDURE ProcessSource(FileID : string);
  141.  
  142. var
  143.   SourceFile : text;
  144.   SourceRec  : string;
  145.   ProcessingUses : boolean;
  146.   FileBuff       : pFileBuff;
  147.  
  148.   procedure CheckSourceIOResult;
  149.     var
  150.       e : integer;
  151.     begin
  152.       e := IOResult;
  153.       if e <> 0 then
  154.         program_i_o_error(e,FileID);
  155.     end; {CheckSourceIOResult}
  156.  
  157.   procedure OpenFile;
  158.     begin
  159.       {$I-}
  160.       Assign(SourceFile,FileID);
  161.       new(FileBuff);
  162.       SetTextBuf(SourceFile,FileBuff^);
  163.       Reset(SourceFile);
  164.       CheckSourceIOResult;
  165.       {$I+}
  166.     end; {OpenFile}
  167.  
  168.   function PartialMatch(substr, target : string) : boolean;
  169.     begin
  170.       if length(target) < length(substr) then
  171.         PartialMatch := false
  172.       else
  173.         begin
  174.           target[0] := char(length(substr));
  175.           PartialMatch := (substr = target);
  176.         end;
  177.     end; {PartialMatch}
  178.  
  179.   procedure ProcessUnit(FileName : string);
  180.     var
  181.       s : string;
  182.     begin
  183.       s := GetThePath(FileName);
  184.       if s <> '' then
  185.         begin
  186.           s := path_plus_file_id(s,FileName);
  187.           ProcessSource(s);
  188.         end;
  189.     end; {ProcessUnit}
  190.  
  191.   procedure ProcessUses(s : string);
  192.     var
  193.       x : byte;
  194.       i : integer;
  195.       UnitName : string;
  196.     begin
  197.       if not ProcessingUses then
  198.         Delete(s,1,5);
  199.       s := StripRec(s);
  200.       While (s <> '') do begin
  201.         x := pos(',',s);
  202.         if x = 0 then
  203.           x := pos(';',s);
  204.         if x = 0 then
  205.           x := length(s) + 1;
  206.         UnitName := StripRec(copy(s,1,x-1)) + '.PAS';
  207.         i := UnitColl^.Count;
  208.         UnitColl^.Insert(NewStr(UnitName));
  209.         if UnitColl^.Count > i then
  210.           ProcessUnit(UnitName);
  211.         if x > length(s) then
  212.           s := ''
  213.         else
  214.           delete(s,1,x);
  215.       end; {of While}
  216.     end; {ProcessUses}
  217.  
  218.   procedure ProcessIncludes(s : string);
  219.     var
  220.       x : byte;
  221.       i : integer;
  222.       UnitName : string;
  223.     begin
  224.       Delete(s,1,4);
  225.       s := StripRec(s);
  226.       x := 1;
  227.       while (x <= length(s)) and (s[x] <> ' ') and (s[x] <> '}') do inc(x);
  228.       UnitName := copy(s,1,x-1);
  229.       i := UnitColl^.Count;
  230.       UnitColl^.Insert(NewStr(UnitName));
  231.       if UnitColl^.Count > i then
  232.         ProcessUnit(UnitName);
  233.     end; {ProcessIncludes}
  234.  
  235.   procedure ProcessFile;
  236.     var
  237.       done : boolean;
  238.       s    : string;
  239.     begin
  240.       done := eof(SourceFile);
  241.       ProcessingUses := false;
  242.       if FirstFileID = '' then
  243.         FirstFileID := FIleID;
  244.       While not done do begin
  245.         {$I-} Readln(SourceFile,SourceRec); {$I+}
  246.         CheckSourceIOResult;
  247.         s := StripRec(SourceRec);
  248.         if (ProcessingUses) or (PartialMatch('USES ',s)) then
  249.           begin
  250.             ProcessUses(s);
  251.             ProcessingUses := (Pos(';',s) = 0);
  252.           end
  253.         else
  254.         if PartialMatch('{$I ',s) then
  255.           ProcessIncludes(s)
  256.         else
  257.         if (FIleID <> FirstFileID) and (PartialMatch('IMPLEMENTATION ',s)) then
  258.           done := true;
  259.         if not done then
  260.           done := eof(SourceFile);
  261.       end; {of While}
  262.     end; {ProcessFile}
  263.  
  264.   procedure CloseFile;
  265.     begin
  266.       {$I-} Close(SourceFile); {$I+}
  267.       CheckSourceIOResult;
  268.       dispose(FileBuff);
  269.     end; {CloseFile}
  270.  
  271. begin {ProcessSource}
  272.   writeln('ProcessSource: ',FileID);
  273.   OpenFile;
  274.   ProcessFIle;
  275.   CloseFile;
  276.   writeln('Done with ',FileID);
  277. end; {ProcessSource}
  278.  
  279. PROCEDURE Closing;
  280.  
  281. begin
  282.   CurrStartCommentDelim := '';
  283. end; {Closing}
  284.  
  285.  
  286. BEGIN
  287.   Initialize;
  288.   ProcessSource(SourceFileID);
  289.   Closing;
  290.   UnitCrossReference := UnitColl;
  291. END;
  292.  
  293. end.
  294.